﻿using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Json;
using System.Windows;
using Microsoft.Win32;

namespace SkyCli.OAuth
{
    public class OAuthService
    {
        public string GetAccessToken(string clientId)
        {
            return CheckFreshToken(clientId) ?? GetNewToken(clientId);
        }

        private string CheckFreshToken(string clientId)
        {
            string token = null;

            using (var key = Registry.CurrentUser)
            {
                using (var subkey = key.OpenSubKey("Software\\SkyCli"))
                {
                    if (subkey != null)
                    {
                        token = subkey.GetValue("access_token") as string;
                        var refresh = subkey.GetValue("refresh_token") as string;
                        var expires = subkey.GetValue("expires_in") as string;
                        var grantTicks = subkey.GetValue("grant_time") as string;

                        var grantTime = new DateTime(long.Parse(grantTicks));
                        var expireTime = grantTime.AddSeconds(int.Parse(expires));
                        if(DateTime.Now > expireTime)
                        {
                            token = GetTokenFromLive(clientId, refresh, true);
                        }
                    }
                    return token;
                }
            }
        }

        private string GetNewToken(string clientId)
        {
            var app = new Application();
            app.Run(new OAuthConsent(clientId));
            var authCode = CallContext.GetData("skycli_auth_code") as string;
            return GetTokenFromLive(clientId, authCode);
        }

        private string GetTokenFromLive(string clientId, string code, bool isRefresh = false)
        {
            var request = new WebRequestWrapper();
            var grantTime = DateTime.Now.Ticks;
            var codeKey = "code";
            if (isRefresh)
                codeKey = "refresh_token";
            var grantType = "authorization_code";
            if (isRefresh)
                grantType = codeKey;
            var response = request.Post("https://login.live.com/oauth20_token.srf",
                                        string.Format(
                                            "client_id={0}&redirect_uri=https://login.live.com/oauth20_desktop.srf&{2}={1}&grant_type={3}",
                                            clientId, code, codeKey, grantType));
            var serializer = new DataContractJsonSerializer(typeof(TokenData));
            var token = serializer.ReadObject(response.GetResponseStream()) as TokenData;
            using (var key = Registry.CurrentUser.CreateSubKey("Software\\SkyCli"))
            {
                key.SetValue("access_token", token.access_token);
                key.SetValue("expires_in", token.expires_in);
                key.SetValue("refresh_token", token.refresh_token);
                key.SetValue("grant_time", grantTime);
            }
            return token.access_token;
        }
    }
}
